Curso de ScriptVox Intermedirio - Aula 2 - Prof. Oswaldo Vernet - iNCE/UFRJ

O objetivo desta segunda aula  introduzir o conceito de chamada de funo.

Como motivao, vamos partir de uma situao concreta: desejamos construir um
pequeno jogo, no qual usurio e computador so adversrios. O jogo ser bem
simples: a cada partida, os dois jogadores lanam dois dados e quem obtiver
o maior nmero de pontos vence a partida. Ser o vencedor do jogo quem somar
o maior nmero de vitrias nas partidas.

Apenas com o exame do enunciado, j podemos destacar um procedimento que ser
utilizado repetidas vezes durante o jogo, pelos dois jogadores: lanar dois
dados simultaneamente e somar os nmeros obtidos nos dois.

Computacionalmente, lanar um dado consiste em obter um nmero gerado aleatoriamente
entre 1 e 6. Nas verses anteriores do ScriptVox, isto era feito da seguinte
maneira: no incio do script, colocvamos o comando RANDOMIZA, responsvel por
configurar o gerador aleatrio. Em qualquer ponto do script, sempre que precisvamos
gerar um nmero aleatrio, usvamos, por exemplo, o comando

seja n RAND 6
soma n 1 

que funciona assim: a funo RAND ir gerar um nmero entre 0 e o limite especificado
menos um, no caso, entre 0 e 5, e este nmero ser atribudo  varivel "n". Depois,
o valor de "n"  incrementado, de modo que, aps estes dois comandos, teremos um
nmero aleatoriamente gerado entre 1 e 6 guardado na varivel "n".

Como estamos abandonando o comando Seja e j aprendemos a fazer atribuies na
aula passada, devemos reescrever estes comandos da seguinte forma:

n := rand 6
n := n + 1

Opcionalmente, e isto  importante por uma questo de legibilidade, podemos colocar
o limite que  fornecido  funo RAND entre parnteses, assim:

n := rand (6)
n := n + 1

Isto  uma questo de estilo, no  obrigatrio, mas facilita bastante a leitura e
a compreenso. Observe que, mesmo nesta nova verso, o comando RANDOMIZA continua 
sendo necessrio no incio do script.

Tambm podemos juntar as duas atribuies numa s:

n := 1 + rand (6)

Assim, o lanamento de dois dados e a soma dos pontos pode ser implementada pela 
seguinte sequncia de trs atribuies:

dado1  := 1 + rand (6)
dado2  := 1 + rand (6)
pontos := dado1 + dado2

Voc conseguiria reduzir ainda mais esta sequncia de comandos, condensando-a numa
nica atribuio?

Notou que apareceu uma novidade nas expresses?  At a aula anterior, elas
eram compostas de operandos e de operadores. Agora apareceu um novo elemento, que 
funciona ao mesmo tempo como operando e como operador: a chamada da funo RAND.

Esta chamada funciona como operador se raciocinarmos da seguinte forma: o valor
que  informado  funo como limite (no caso 6)  usado para produzir como resultado
um nmero. Portanto, a funo RAND vai agir sobre este limite, provavelmente fazendo
algumas contas onde ele aparece, para produzir o valor desejado.
Lembra-se do que fazia um operador? Ele agia sobre os operandos, combinando seus valores.

E por que dissemos que a chamada da funo RAND funciona tambm como operando? Porque
o valor calculado pela funo (o nmero entre 0 e 5)  o valor que vai ser somado com o
inteiro 1, para produzir o nmero de 1 a 6 que desejamos. Ento, este valor retornado 
pela funo funciona exatamente como um operando na expresso.

Os operadores que vimos at agora (soma, multiplicao, subtrao, diviso, resto da
diviso e concatenao) agem sempre sobre dois operandos e, por isso, so denominados
OPERADORES BINRIOS. Mas a chamada da funo RAND, no exemplo acima, age sobre um nico
operando e, por isso,  denominada um OPERADOR UNRIO.  Que outro operador unrio voc
conhece desde o ensino fundamental, em matemtica?

Mas existem funes que agem sobre dois operandos, trs, quatro, etc..., funcionando
como operadores BINRIOS, TERNRIOS, QUATERNRIOS, etc... Teremos oportunidade, em aulas
futuras, de mostrar algumas delas.

Voltando ento ao nosso exemplo, examinemos como funciona exatamente a atribuio

dado1 := 1 + rand (6)

O ScriptVox realizar a seguinte sequncia de passos quando se deparar com este comando
para interpretar:

- primeiramente ele percebe que se trata de um comando de atribuio, em que a varivel
  a ser modificada  "dado1", por estar  esquerda do sinal de atribuio ":=";
- em seguida, o ScriptVox precisa avaliar a expresso que aparece ao lado direito do sinal
  ":="; esta expresso consiste no inteiro 1 somado ao valor retornado pela funo RAND
  agindo sobre o inteiro 6;
- portanto, o prximo passo, ser CHAMAR a funo RAND, informando a ela o inteiro 6;
- a funo RAND  uma funo interna do ScriptVox: de posse do inteiro 6, ela far algumas
  contas e produzir como resultado um nmero de 0 a 5;
- este nmero , portanto, o valor RETORNADO pela funo;
- o ScriptVox, ento, prossegue na avaliao da expresso, somando 1 com o valor retornado
  pela funo RAND;
- por fim, o valor resultante desta soma ser atribudo  varivel "dado1"; se havia algum
  valor anteriormente armazenado em "dado1", ele  perdido.

Existem analogias entre chamadas de funes e algumas situaes da vida quotidiana que
podem ser proveitosas ao entendimento. Suponha que voc se dirige ao caixa do banco, tendo
em mos uma conta para pagar e o dinheiro exato do valor da conta. Como funcionar o caixa
do banco? Para voc, usurio, isto  totalmente irrelevante. O que importa  que voc informou
o valor a ser pago e forneceu o dinheiro. Quantos botes o caixa precisar apertar, quantas
gavetas ele ir abrir e fechar, nada disso lhe interessa. O que importa para voc  o resultado:
o recibo dizendo que a conta est quitada.

Neste caso, o caixa do banco funciona exatamente como uma funo: quando chamada, ela espera
receber algumas informaes (no caso, o papel contendo o valor da conta e o dinheiro) e deve
emitir como resposta algo previsvel, ou seja, que esteja dentro de certas especificaes
(no caso, o recibo quitado e, possivelmente, algum troco). O que o caixa fez,
se ele pensou muito ou pouco, se foi difcil ou fcil processar o seu pagamento, no interessa.
Voc quer  o recibo dizendo que pagou a conta.

Repare em mais um ponto: o que voc fica fazendo enquanto o caixa do banco processa o seu
pagamento? Bom,  claro, voc pode falar no celular, assobiar, reclamar que est demorando,
pensar na morte da bezerra, etc... Mas, olhando sua ida ao banco como parte de um script,
voc simplesmente ficar esperando o caixa trabalhar e s prosseguir aps ter em mos o 
recibo quitado.

O mesmo ocorre na avaliao de uma expresso quando uma chamada de funo  encontrada:
a avaliao deve esperar at que a funo termine o seu processamento e fornea o valor
de retorno. S ento a avaliao pode prosseguir, usando como operando o valor retornado pela 
funo.

Quando se chama uma funo, podemos informar a ela alguns valores, que sero necessrios 
ao seu processamento. Estes valores so chamados PARMETROS para a funo.
Valores diferentes podem acarretar processamentos tambm diferentes por parte da funo. 

Imagine de novo o exemplo do caixa: os parmetros so a conta a pagar e o dinheiro. 
H trs possibilidades: se o dinheiro est contadinho, volta s o recibo; se o dinheiro 
 superior ao valor da conta, voltam recibo e troco; se o dinheiro no  suficiente, 
o caixa lhe dir que no pode processar o pagamento.

Portanto, o processamento que a funo realiza varia com os parmetros que ela recebe.
Reparou que o retorno tambm pode variar? No primeiro caso, s volta o recibo; no segundo, 
voltam recibo e troco; no terceiro caso, volta uma informao: "t faltando, meu camarada".

O que  importante informar ao programador que ir utilizar uma funo no seu programa? 
Certamente, o que ela faz  importante. Mas alm disso, devemos informar tambm como cham-la 
(isto , quais parmetros ela espera) e o que ela retorna. Por exemplo, de nada adiantaria
voc dirigir-se ao caixa do banco e entregar-lhe um romance de Paulo Coelho: ele no teria
o que fazer com o livro.

No entanto, existem funes que no necessitam de informao alguma para processar. So funes
que no esperam nada e retornam algo. Voc consegue imaginar alguma?

Um ltimo ponto: nomes de comandos e nomes de funes so PALAVRAS RESERVADAS na nova
verso do ScriptVox. Isto significa que no  permitido ter nomes de variveis iguais a 
nomes de funes ou iguais a nomes de comandos. Para isto, sempre que for inventar um nome
para uma varivel, lembre-se que os comandos que temos at agora so os seguintes:

        ABRE ACIONA  
		BIPA BUSCA
        CAPTURA CHAMA CHECA CLICA CMD CONCATENA CONECTA CONTINUA COPIA COR
        DEBUG DESVIA DIGITA DIR DIVIDE
        ENQUANTO ESCREVE ESPERA EXECUTA
		FALA FECHA FIM FUNCAO FUNDO
        IMAGEM IMPORTA INTERNET IP
        JANELA
        LE
        MCI MENU MSAA MULTIPLICA
        OBSERVA
        PARA
        QUEBRA
        RANDOMIZA REMOVE RENOMEIA REPETE REPLICA RETORNA
        SE SEJA SENAO SENSOR SERVE SIMBOLOS SOMA SUBSTITUI SUBTRAI
        TELA TERMINA TOCA TRANSFERE

e as funes so:
		
        CHAVES
        DATA DIA DIRETORIO DUPLICA
        FALSE FALSO FDA FIMARQ
        HORA
        INDEFINIDO INSERE INTEIRO
        JUNTA JUSTIFICA
        MAIUSC MAP
        NAO NOT
        ORDENA
        PALAVRA POS
        RAND RETIRA
        SEPARA
        TAMANHO TEMPO TIPO TOKENS TRIM TRUE
        VERDADEIRO

No, voc no precisa decorar esta lista! Quando, por esquecimento, voc usar um desses nomes,
o ScriptVox acusar erro e voc dever trocar por outro. Se voc realmente quiser batizar alguma
varivel com um desses nomes,  simples: use o velho cifro na frente; desta forma, o nome ficar
distinto de qualquer PALAVRA RESERVADA.

Como o interpretador ainda est em fase de ajustes, esta lista de palavras reservadas pode sofrer
modificaes. No manual final, a lista estar completa e ser definitiva.


EXERCCIOS

Perguntas de Estudo Dirigido:

1) Invente uma outra analogia entre chamadas de funes e uma situao da vida quotidiana.
   Lembre-se de deixar claro quais so os parmetros e o que a funo retorna.
   
2) No texto, descrevemos uma situao em que apenas uma chamada de funo ocorre durante
   a avaliao de uma expresso. O que acontece, por exemplo, se tivermos a seguinte expresso:
   
      pontos := 2 + rand (6) + rand (6)
   
   onde aparecem duas chamadas  funo RAND?
   
3) Um programador inteligente pensaria em substituir a atribuio

      pontos := 2 + rand (6) + rand (6)
   
   na qual a chamada da funo RAND aparece duas vezes seguida, com o mesmo parmetro (o inteiro 6),
   pela seguinte atribuio:
   
      pontos := 2 + 2 * rand (6)
   
   Explique ao programador por que as duas atribuies no so equivalentes, embora paream.

4) Uma funo que espera um parmetro funciona como operador unrio. Se esperar dois, funcionar como
   operador binrio; trs, ternrio, etc... E quando a funo no requer parmetros, ela funciona como
   um operador de que tipo?


Exerccios de Programao

1) Na resoluo da segunda questo do teste de autoavaliao, voc deve ter usado um comando do tipo

   Seja p POS ":" $linha

   para saber em que posio ocorre o caractere ":" na cadeia armazenada em $linha.

   No ScriptVox verso 6.0, este comando pode ser reescrito como uma atribuio:

   p := POS (":", $linha)

Modifique o script que voc escreveu para resolver a questo, usando atribuies.

2) A funo PALAVRA espera duas informaes: um nmero inteiro e uma cadeia de caracteres.
   O que ela faz  extrair da cadeia a palavra de ordem especificada pelo nmero. Assim
   
   p := PALAVRA (2, "o gato subiu no telhado")
   
   a funo PALAVRA ir procurar a segunda palavra na cadeia "o gato subiu no telhado" e
   ir retornar a cadeia "gato", que ser atribuda  varivel "p".
   
   Escreva um pequeno script que l do teclado uma frase sem pontuao e escreve na tela todas 
   as palavras da frase, uma por linha.
   
3) Todas as opes do comando SEJA, como DATA, HORA, TEMPO, etc... esto disponveis na verso 6.0
   tambm como chamadas de funes. Assim, podemos escrever

   bomdia := "Rio de Janeiro, " + data() + ", " + hora()

   Experimente esta atribuio no novo interpretador e observe o contedo da varivel "bomdia"
   (mande escrever na tela). Pode trocar "Rio de Janeiro" pelo nome da sua cidade.

   Observou que "data()" e "hora()" so chamadas de funes?  Elas no precisam de nenhuma
   informao para processar, apenas retornam a data e a hora correntes. Isto  indicado pelo
   abre e fecha parnteses sem nada dentro. Experimente tirar o abre e fecha parnteses.
   Funciona tambm?
   
   Agora pense um pouco: por que o ScriptVox no implementa data e hora como variveis em vez
   de funes?
   
4) Descanse.


Exerccio de Avaliao (envie at meio-dia de 23 de janeiro para scriptvox@gmail.com):

Escreva o script que implementa o joguinho descrito no incio do texto desta aula. Procure criar
subrotinas e usar o comando CHAMA em vez de repetir as mesmas linhas em diversos
pontos do cdigo. Seja gentil com o usurio: pergunte seu nome, diga bom dia, informe a data,
a hora, tudo arrumadinho. Opcionalmente, fornea as regras do jogo (se o usurio assim o desejar).

Lembre-se que a extenso a partir de agora  ".PRO", para o nome do script.

Bom estudo!

Oswaldo Vernet







